using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Xml;

namespace HWEngine.Configuration
{
	[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	internal class ConfigAttibute : Attribute
	{
		private Type _formatter = null;

		public ConfigAttibute(Type formatter)
		{
			_formatter = formatter;
		}

		public Type FormatterType
		{
			get { return _formatter; }
		}
	}

	public class BaseConfigurator
	{
		protected BaseConfigurator()
		{
			LoadConfig();
		}

		public virtual String ConfigFileName
		{
			get { return Path.Combine(Application.StartupPath, "config.xml"); }
		}

		public void SaveConfig()
		{
			XmlDocument xmlDoc = new XmlDocument();
			xmlDoc.LoadXml("<config/>");
			Dictionary<string, PropertyInfo> properties = GetPropertiesCollection();
			foreach (KeyValuePair<string, PropertyInfo> keyvalue in properties)
			{
				PropertyInfo property = keyvalue.Value;
				XmlElement el = xmlDoc.CreateElement("property");
				el.SetAttribute("name", keyvalue.Key);
				Object value = property.GetValue(this, null);
				ConfigAttibute attribute = ((ConfigAttibute) (property.GetCustomAttributes(typeof (ConfigAttibute), false)[0]));
				IStringFormatter formatter = (IStringFormatter) Activator.CreateInstance(attribute.FormatterType);
				String valueStr = formatter.ToString(value);
				el.SetAttribute("value", valueStr);
				xmlDoc.DocumentElement.AppendChild(el);
			}
			xmlDoc.Save(ConfigFileName);
		}

		private void LoadConfig()
		{
			try
			{
				Dictionary<string, PropertyInfo> properties = GetPropertiesCollection();
				XmlDocument xmlDoc = new XmlDocument();
				xmlDoc.Load(ConfigFileName);
				XmlNodeList nodes = xmlDoc.SelectNodes("//property");
				foreach (XmlElement xmlEl in nodes)
				{
					String name = xmlEl.GetAttribute("name");
					String valueStr = xmlEl.GetAttribute("value");

					if (properties.ContainsKey(name))
					{
						PropertyInfo property = properties[name];
						ConfigAttibute attribute = ((ConfigAttibute) (property.GetCustomAttributes(typeof (ConfigAttibute), false)[0]));
						IStringFormatter formatter = (IStringFormatter) Activator.CreateInstance(attribute.FormatterType);
						object value = formatter.FromString(valueStr, property.PropertyType);
						properties[name].SetValue(this, value, null);
					}
				}
			}
			catch
			{
			}
		}

		private Dictionary<string, PropertyInfo> GetPropertiesCollection()
		{
			Dictionary<string, PropertyInfo> result = new Dictionary<string, PropertyInfo>();
			PropertyInfo[] properties;
			Type type = GetType();
			properties = type.GetProperties();
			foreach (PropertyInfo property in properties)
			{
				if (property.IsDefined(typeof (ConfigAttibute), false))
				{
					result.Add(property.Name, property);
				}
			}
			return result;
		}
	}
}